#pragma once
#include <list>
#include <algorithm>

typedef enum _tagPRESSMODE
{
	NoPress		= 0x00,
	Ctrl		= 0x01,
	Shift		= 0x02,
	CtrlShift	= 0x03
}PRESSMODE;


typedef enum _tagASSISTMODE
{
	KeyBoard	= 0x10,
	Mouse		= 0x20
}ASSISTMODE;

using namespace std;
typedef list<int> INT_LIST, *PINT_LIST;

typedef INT_LIST::iterator INTLISTITER;

class IPress
{
public:
	virtual ~IPress() {}
	virtual void Handle(int* pOriginal, int nTarget, PINT_LIST pListSelected) = 0;
};

class CNoPress : public IPress
{
public:
	virtual void Handle(int* pOriginal, int nTarget, PINT_LIST pListSelected);
};

class CCtrl : public IPress
{
public:
	virtual void Handle(int* pOriginal, int nTarget, PINT_LIST pListSelected);
};

class CShift : public IPress
{
public:
	virtual void Handle(int* pOriginal, int nTarget, PINT_LIST pListSelected);
};

class CCtrlShift : public IPress
{
public:
	virtual void Handle(int* pOriginal, int nTarget, PINT_LIST pListSelected);
};

class IAssist
{
public:
	virtual ~IAssist(){}
	virtual int GetTarget(int nOriginal, int nLastTarget, int nEndIndex, int nHit) = 0;
};

class CKeyBoardAssist : public IAssist
{
public:
	CKeyBoardAssist(){}
	virtual int GetTarget(int nOriginal, int nLastTarget, int nEnd, int nHit);
};

class CMouseAssist : public IAssist
{
public:
	CMouseAssist(){}
	virtual int GetTarget(int nOriginal, int nLastTarget, int nEnd, int nHit);
};

class UIListSelector;
interface IState
{
public:
	virtual void Select(int nHit, PINT_LIST pListSelected) = 0;
	virtual void SetOwner(UIListSelector* pOwner) = 0;
};



template<class Press, class Assist>
class CState : public IState
{
public:
	CState()
	{	
	}
	
	void SetOwner(UIListSelector* pOwner)
	{
		m_pOwner = pOwner;
	}

	void Select(int nHit, PINT_LIST pListSelected)
	{
		if(NULL == m_pOwner)
		{
			return;
		}

		int nOriginal = m_pOwner->GetOriginal();
		int nEnd = m_pOwner->GetEnd();

		int nLastTarget = m_pOwner->GetLastTarget();
		int nTarget = m_Assist.GetTarget(nOriginal, nLastTarget, nEnd, nHit);

		m_Press.Handle(&nOriginal, nTarget, pListSelected);

		m_pOwner->SetOriginal(nOriginal);
		m_pOwner->SetLastTarget(nTarget);
	}


private:
	Press			m_Press;
	Assist			m_Assist;
	UIListSelector	*m_pOwner;	
	INT_LIST			m_listSelect;
};

class CStateFactory
{
public:
	static IState*	CreateState(ASSISTMODE AssistMode, PRESSMODE PressMode);
	static void		ReleaseState(IState* pState);	
};

interface IHost
{
public:
	virtual bool CascadeSelect(int nIndex) = 0;
	virtual void CascadeNotify(list<int> listIndex) = 0;
	virtual bool CascadeUnSelect(int nIndex) = 0;
	virtual int  GetSelectableCount() = 0;
};


class UIListSelector
{
public:
	UIListSelector();
	virtual ~UIListSelector(void);

	void	EnterState(ASSISTMODE AssistMode, PRESSMODE PressMode);
	void	Select(int nHit);
	INT_LIST GetSelectedItems();
	int		GetOriginal();
	void	SetOriginal( int nOriginal );
	int		GetLastTarget();
	void	SetLastTarget( int nLastTarget );
	int		GetEnd();	
	void	RemoveAt(int nIndex);
	void	Clear();
	void	SetHost( IHost* pHost );
private:
	IState	*m_pState;
	IHost	*m_pHost;
	int		m_nLastTarget;
	int		m_nOriginal;
	INT_LIST	m_listSelected;
};
